import { Body, Controller, Get, Post, Req } from '@nestjs/common';
import { Request } from 'express';
import { ApiException } from 'src/exception/api.exception';
import { QrCodeService } from 'src/service/qrcode.service';
import { QrcodeContext, QrCodeStatus } from 'src/types/qrcode.context';
import { CodeGenerator } from 'src/utils';
import { JWTUtil } from 'src/utils/jwt';
import { LoginRequest, ResultBean, VaildScanCodeEntity } from '../../types'


@Controller('/sv')
export class QrcodeController {

    private readonly codeContextMap: Map<string, QrcodeContext> = new Map();

    constructor(
        readonly qrCodeService: QrCodeService
    ) { }

    @Get("/qrCode")
    async qrCode(): Promise<ResultBean> {
        const currentTimes = Date.now();
        const uuid: string = CodeGenerator.generateUUID();

        const qrBuf = this.qrCodeService.generateQrCode("login:=" + JSON.stringify({ channelId: uuid }), { size: 25 });
        let qrBase64: string = qrBuf.toString("base64")


        let qc = new QrcodeContext(uuid, currentTimes + (1000 * 60 * 5));


        this.codeContextMap.set(uuid, qc);

        const result =ResultBean.success(qrBase64);
        (result as any).channelId= uuid;
        return result;
    }

    @Post("/vaildScanCode")
    async vaildScanCode(@Body() ventity: VaildScanCodeEntity): Promise<ResultBean> {


        const qrContext = this.codeContextMap.get(ventity.channelId)

        const result = ResultBean.success(null);


        // 判断二维码是否已不存在
        if (!qrContext) {

            (result as any).status = QrCodeStatus.CODE_INVALIDATE;

        } else if (qrContext.status == QrCodeStatus.CODE_INVALIDATE) {
            (result as any).status = QrCodeStatus.CODE_INVALIDATE;
            this.codeContextMap.delete(ventity.channelId)
        } else {
            (result as any).status = qrContext.status;
            (result as any).token = qrContext.token;
        }


        return result;
    }

    @Post("/scanCode")
    async scanCode(@Body() ventity: VaildScanCodeEntity): Promise<ResultBean> {
        const qrContext = this.codeContextMap.get(ventity.channelId)


        if (!qrContext || qrContext.status == QrCodeStatus.CODE_INVALIDATE) {
            throw new ApiException("二维码无效")
        }

        if (Date.now() <= qrContext.expTimes) {
            qrContext.status = QrCodeStatus.SCANED;
            return ResultBean.successMsg("扫码状态已设置");
        } else {
            qrContext.status = QrCodeStatus.CODE_INVALIDATE;
            return ResultBean.error("二维码已过期");
        }
    }

    @Post("/confim")
    async confim(@Body() ventity: VaildScanCodeEntity & { accept: boolean }, @Req() req: LoginRequest) {
        const qrContext = this.codeContextMap.get(ventity.channelId)


        if (!qrContext || (qrContext.status != QrCodeStatus.SCANED && this.codeContextMap.delete(ventity.channelId))) {
            throw new ApiException("二维码无效")
        }

        // 用户取消扫码
        if (!ventity.accept) {
            qrContext.changeStatus(QrCodeStatus.USER_CANCEL)
            return ResultBean.builder({ data: "0", msg: "取消扫码", code: "200" })
        }

        const token: string = JWTUtil.generateToken({ uid: req.currentUser() }, 60 * 60 * 24 * 7)

        // 确认扫码登陆
        qrContext.changeStatus(QrCodeStatus.USER_CONFIRM);
        qrContext.token = token;

        return ResultBean.builder({ code: "200", data: 1, msg: "扫码确认完成" });

    }


}
